Introduction
This is simply a presentation of a class which can be used as an intermediate class for owner draw buttons.
Using the code
When an owner draw button is created, we begin like...
class CMyButton : public CButton
{
};
What I did was that I derived a class from CButton
named CODBaseBtn
, that does nothing related to drawing. Instead, some virtual functions are called. This made it an intermediate class for owner draw buttons.
class CODBaseBtn : public CButton
{
}
There are two kinds of virtual functions provided:
- Drawing related
- Action related
The drawing related virtual functions are as follows...
virtual void OnDrawNormal( CDC& dc, CRect rect ) = 0;
virtual void OnDrawHovered( CDC& dc, CRect rect ) { OnDrawNormal( dc, rect ); }
virtual void OnDrawPressed( CDC& dc, CRect rect ) { OnDrawNormal( dc, rect ); }
virtual void OnDrawDisabled( CDC& dc, CRect rect ) { OnDrawNormal( dc, rect ); }
The first function is pure virtual, which must be implemented by the derived classes. As the names imply, these functions are called on the corresponding conditions. So the derived class can handle them and draw the appropriate button images.
The action related virtual functions are as follows...
virtual void OnBeginHover() { }
virtual void OnEndHover() { }
virtual void OnPressed() { }
virtual void OnReleased() { }
They are called on the actions like mouse hover, mouse leave, press, and release, respectively. They can be used wisely to extend the functionality of a normal button. They are not pure virtual, so they can be avoided if not needed.
Deriving a class from CODBaseBtn
is as shown...
class CMyBtn : public CODBaseBtn
{
}
Sample application
The sample test application has two derived classes. One is just using the drawing related functions. While the other uses both drawing and action related functions. From that, the possibilities of such a class can be understood.
The drawing done is very simple since the test application is just for illustrating the use of CODBaseBtn
.
Inside CODBaseBtn
The main code inside CODBaseBtn
is described here:
void CODBaseBtn::PreSubclassWindow()
{
ModifyStyle( 0, BS_OWNERDRAW );
}
The style is set to BS_OWNERDRAW
for enabling the button owner draw. This helps to avoid setting this style when the button is created, either in the dialog resource editor or at run time using Create
(or CreateWindow
).
void CODBaseBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
}
DrawItem
is a virtual function of CButton
. It is called when the button needs to be drawn. The lpDrawItemStruct
will contain the necessary things for drawing, like hDC, client rectangle, state of the button, etc. Using these, the appropriate virtual functions for drawing and action are called.
void CODBaseBtn::OnMouseMove(UINT nFlags, CPoint point)
{
if( !m_bMouseHover )
{
m_bMouseHover = true;
}
}
This is for mouse hover handling. When the mouse is inside the button, m_bMouseHover
will be false
(which is initially set as false
). And inside the function, it is set as true
. So when the mouse moves inside the button the next time, it can be neglected. The first time, the corresponding drawing and action functions are called and the mouse leave message request is registered using _TrackMouseEvent
. The following function will be called when the mouse leaves the button (client) area.
LRESULT CODBaseBtn::OnMouseLeave( WPARAM, LPARAM )
{
m_bMouseHover = false;
return 0;
}
Here, m_bMouseHover
is reset to false
. And the necessary calls to drawing and action functions are called:
void CODBaseBtn::OnLButtonDblClk(UINT nFlags, CPoint point)
{
const MSG* pstMSG = GetCurrentMessage();
DefWindowProc( WM_LBUTTONDOWN, pstMSG->wParam, pstMSG->lParam );
}
This is a tricky one. Buttons having the BS_OWNERDRAW
style will not respond to double click as normal buttons do. So the solution is as above. When the double click occurs, call the default window procedure of the button with WM_LBUTTONDOWN
instead of the actual WM_LBUTTONDBLCLK
.
Conclusion
The class provided can be used as a layer between CButton
and the derived class for an owner draw button. It will help to avoid a lot of code and is pretty useful.
History
None.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.